package io.gitee.dtdage.app.boot.starter.data.mybatis.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import io.gitee.dtdage.app.boot.starter.common.BaseEntity;
import io.gitee.dtdage.app.boot.starter.data.mybatis.context.PageBean;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;

/**
 * 公共CRUD接口
 *
 * @author WFT
 * @since 2024/4/14
 */
public interface BaseService<T extends BaseEntity> {

    /**
     * 新增一条数据
     *
     * @param param 数据
     * @return {@link BaseEntity}
     */
    T create(T param);

    /**
     * 根据主键删除一条数据
     *
     * @param masterKey 主键
     */
    void delete(Serializable masterKey);

    /**
     * 根据主键列表删除多条数据
     *
     * @param list {@link List}
     */
    void delete(Collection<? extends Serializable> list);

    /**
     * 根据条件删除多条数据
     *
     * @param consumer 删除条件
     */
    void delete(Consumer<LambdaUpdateWrapper<T>> consumer);

    /**
     * 根据主键修改单条数据
     *
     * @param param 需要更新的数据,主键不能为空
     */
    void update(T param);

    /**
     * 根据主键修改多条数据
     *
     * @param param 需要更新的数据
     * @param list  主键列表
     */
    default void update(T param, Collection<? extends Serializable> list) {
        this.update(param, wrapper -> wrapper.in(T::getId));
    }

    /**
     * 根据条件修改多条数据
     *
     * @param param    需要更新的数据
     * @param consumer 修改条件
     */
    void update(T param, Consumer<LambdaUpdateWrapper<T>> consumer);

    /**
     * 根据条件修改多条数据
     *
     * @param consumer 修改条件
     */
    default void update(Consumer<LambdaUpdateWrapper<T>> consumer) {
        this.update(null, consumer);
    }

    /**
     * 指定字段自增
     *
     * @param attribute 指定的字段
     * @param number    正数为增,负数为减
     * @param consumer  {@link Consumer}
     */
    default void increment(String attribute, Integer number, Consumer<LambdaUpdateWrapper<T>> consumer) {
        String sql = String.format("%s = %s + (%d)", attribute, attribute, number);
        this.update(wrapper -> consumer.accept(wrapper.setSql(sql)));
    }

    /**
     * 根据主键查询
     *
     * @param masterKey 主键
     * @return {@link BaseEntity}
     */
    T get(Serializable masterKey);

    /**
     * 根据条件查询
     *
     * @param consumer 查询条件
     * @return {@link BaseEntity} 如果结果不唯一,将抛出异常
     */
    T get(Consumer<LambdaQueryWrapper<T>> consumer);

    /**
     * 查询列表
     *
     * @return {@link List}
     */
    default List<T> query() {
        return this.query(wrapper -> {

        });
    }

    /**
     * 根据主键列表查询
     *
     * @param list 主键列表
     * @return {@link List}
     */
    default List<T> query(Collection<? extends Serializable> list) {
        return this.query(wrapper -> wrapper.in(T::getId, list));
    }

    /**
     * 根据条件查询列表
     *
     * @param consumer 查询条件
     * @return {@link List}
     */
    List<T> query(Consumer<LambdaQueryWrapper<T>> consumer);

    /**
     * 查询总记录数
     *
     * @return {@link Long}
     */
    default long count() {
        return this.count(wrapper -> {

        });
    }

    /**
     * 根据条件查询总记录数
     *
     * @param consumer 查询条件
     * @return {@link Long}
     */
    long count(Consumer<LambdaQueryWrapper<T>> consumer);

    /**
     * 分页查询
     *
     * @param page 分页条件
     * @return {@link PageBean}
     */
    default <Page extends PageBean<T>> Page page(Page page) {
        return this.page(page, wrapper -> {

        });
    }

    /**
     * 根据条件分页查询
     *
     * @param page     分页条件
     * @param consumer 查询条件
     * @return {@link PageBean}
     */
    <Page extends PageBean<T>> Page page(Page page, Consumer<LambdaQueryWrapper<T>> consumer);

}
